package com.hmall.search.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.domain.PageDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.BeanUtils;

import com.hmall.item.domain.po.ItemDoc;
import com.hmall.search.domain.dto.ItemDTO;
import com.hmall.search.domain.dto.OrderDetailDTO;
import com.hmall.search.domain.po.Item;
import com.hmall.search.domain.query.ItemPageQuery;
import com.hmall.search.mapper.ISearchMapper;
import com.hmall.search.service.ISearchService;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author 虎哥
 */
@Service
public class ISearchServiceImpl extends ServiceImpl<ISearchMapper, Item> implements ISearchService {
        @Resource(name="elasticSearchClient")
        private RestHighLevelClient restHighLevelClient;


        @Override
    @Transactional
    public void deductStock(List<OrderDetailDTO> items) {
        String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock";
        boolean r = false;
        try {
            r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity));
        } catch (Exception e) {
            throw new BizIllegalException("更新库存异常，可能是库存不足!", e);
        }
        if (!r) {
            throw new BizIllegalException("库存不足！");
        }
    }

    @Override
    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
        return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
    }

    @Override
    public PageDTO EsSearch(ItemPageQuery query) {
            restHighLevelClient=new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.100.101", 9200)));
       //1.准备request对象
        SearchRequest request = new SearchRequest("items");
        //2.求出总数
        request.source().trackTotalHits( true);
        //3.准备参数
        //3.1组织DSL参数
        //bool查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //关键词查询
        if (query.getKey() != null) {
            boolQuery.must(QueryBuilders.matchQuery("name", query.getKey()));
        }
        //分类查询
        if(query.getCategory() != null){
            boolQuery.must(QueryBuilders.matchQuery("category", query.getCategory()));
        }
        //品牌查询
        if(query.getBrand() != null){
            boolQuery.must(QueryBuilders.matchQuery("brand", query.getBrand()));
        }
        //价格最大值
        if(query.getMaxPrice() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(query.getMaxPrice()));
        }
        //价格最小值
        if(query.getMinPrice() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(query.getMinPrice()));
        }
      request.source().query( boolQuery);
        //6.分页参数
        request.source().from((query.getPageNo() - 1)*query.getPageSize()).size(query.getPageSize());
        //7.排序
        if(query.getSortBy() != null){
            //如果指定排序字段 先按照指定字段排序 再按照分数排序 最后按照更新时间排序
            request.source().sort(query.getSortBy(), query.getIsAsc() ? SortOrder.ASC : SortOrder.DESC)
                    .sort("updateTime", SortOrder.DESC);
        }else{
            request.source()
                    .sort("updateTime", SortOrder.DESC);
        }
        //8.高亮结果
        request.source().highlighter(SearchSourceBuilder.highlight().field("name"));
        PageDTO<ItemDTO> result =null;
        //发送请求
        try {
            //发送请求
            SearchResponse response= restHighLevelClient.search(request, RequestOptions.DEFAULT);
            //解析结果
            List<ItemDoc> itemDocList=new ArrayList<>();
            SearchHits searchHits= response.getHits();
            //获取总记录数
            long total= 0;
            if (searchHits.getTotalHits() != null) {
                total = searchHits.getTotalHits().value;
            }
            //获取命中的数据
            SearchHit[] hits= searchHits.getHits();
            for (SearchHit hit : hits) {
                //获取source数据
                String json=hit.getSourceAsString();
                //转换成对象
                ItemDoc itemDoc = JSONUtil.toBean(json, ItemDoc.class);
                //获取高亮数据
                Map<String, HighlightField> hfs= hit.getHighlightFields();
                if(hfs!=null && hfs.size()>0){
                    itemDoc.setName(hfs.get("name").getFragments()[0].toString());
                }
                itemDocList.add(itemDoc);
            }
            //转为DTO
            List<ItemDTO> itemDTOList= BeanUtils.copyList(itemDocList, ItemDTO.class);
            //设置页面
            Long pageSize=query.getPageSize().longValue();
            result= new PageDTO<>( total,pageSize ,itemDTOList);


        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        return result;


    }

}
